﻿using Core.Comamad;
using Core.ReadAndWrite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Core
{
    public class QuanLiSinhVien : IQuanLi
    {
        public List<BaseData> data;
     
        #region Singleton
        private static QuanLiSinhVien _Instance;
        private static object locks = new object();

        public static QuanLiSinhVien Instance
        {
            get
            {
                if (_Instance == null)
                {
                    lock (locks)
                    {
                        if (_Instance == null)
                            _Instance = new QuanLiSinhVien();
                    }
                }
                return _Instance;
            }
        }
        #endregion


        #region Command
        List<ICommand> _commands = new List<ICommand>();
        private int Current
        {
            get
            {
                return _commands.Count;

            }
            set
            {
                Current = value;
            }
        }
        public void Undo()
        {
            var count = (int)Current - 1;
            ICommand cms = _commands[count];
            cms.UnExecute();
        }
        #endregion

        #region Observer
        List<IInestor> _investors;
        #endregion
    
        /// <summary>
        /// khoi tao danh sach Sinh Vien:BaseData
        /// IInestor la danh sach cac doi tuong muon xem xu thay doi trong QuanLiSinhVien
        /// </summary>
        public QuanLiSinhVien()
        {
            data = DataSource.Instance.ReadSinhVien("DsSinhVien.txt");
            _investors = new List<IInestor>();
        }

        /// <summary>
        /// duyet qua tat cac cac IInestor de cap nhat lai thay doi 
        /// </summary>
        public void Notify()
        {
            foreach (IInestor investor in _investors)
            {
                investor.Update(this);
            }
          
        }

        /// <summary>
        /// them cac doi tuong anh huong den ket qua
        /// </summary>
        /// <param name="investor"></param>
        public void Attach(IInestor investor)
        {
            _investors.Add(investor);
        }

        /// <summary>
        /// remove doi tuong anh huong den ket qua
        /// </summary>
        /// <param name="investor"></param>
        public void Detach(IInestor investor)
        {
            _investors.Remove(investor);
        }

        public void Add(List<BaseData> ds)
        {
            foreach (var item in ds)
            {
                if (!data.Contains(item))
                {
                    data.AddRange(ds);
                    setSiSo();
                }
            }
       
        }
        public void setSiSo()
        {
            foreach (var item in QuanLyLop.Instance.data)
            {
                Attach(item as LopHoc);
                
            }
            Notify();
        }
        public void Add(BaseData ob)
        {
            data.Add(ob);
            //khoi tao doi tuong commadn
            ICommand temp = new ObCommand(LoaiXuLi.Add, ob);
            _commands.Add(temp);
            Notify();
        }

        public void Delete(BaseData ob)
        {
            ICommand temp = new ObCommand(LoaiXuLi.Remove, ob);
            _commands.Add(temp);
            data.RemoveAll(c => (c as SinhVien).MSSV == (ob as SinhVien).MSSV);
            setSiSo();
        }

        public void Update(BaseData ob)
        {
            SinhVien sv = ob as SinhVien;
            SinhVien find = data.FirstOrDefault(c => (c as SinhVien).MSSV == sv.MSSV) as SinhVien;
            find.TenSV = sv.TenSV;
            find.NamVaoHoc = sv.NamVaoHoc;

        }



        public List<BaseData> FindAll(Predicate<BaseData> Predicate)
        {
            return data.FindAll(Predicate);
        }


        public BaseData Find(Func<BaseData, bool> predicate)
        {
            return data.FirstOrDefault(predicate);
        }
        public override string ToString()
        {
            StringBuilder tem = new StringBuilder();
            foreach (var item in this.data)
            {
                tem.AppendLine(item.ToString());
            }
            return tem.ToString();
        }

        public SinhVien this[int index]
        {
            get {
                return data[index] as SinhVien;
            }
        }
    }

}
